<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!--引入CSS-->
<link rel="stylesheet" type="text/css" href="/static/webuploader.css" th:href="@{/static/webuploader.css}"/>
<!--引入JS-->
<script src="https://s3.pstatp.com/cdn/expire-1-M/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="/static/webuploader.js" th:src="@{/static/webuploader.js}"></script>
<style>
</style>
<body>
<!--首先准备dom结构，包含存放文件信息的容器、选择按钮和上传按钮三个部分。-->
<div id="upload-container">
</div>
<!--用来存放文件信息-->
<div id="list">
</div>
<button id="picker">点击选择文件</button>
<input type='button' id='uploadFile' onclick='uploadFile()' value='开始上传'>
</body>

<script>
    // 注册钩子，注意顺序需要放在 WebUploader.create之前
    WebUploader.Uploader.register({
            //在文件发送之前request，此时还没有分片（如果配置了分片的话），可以用来做文件整体md5验证
            'before-send-file': 'beforeSendFile'
        },
        {
            beforeSendFile: function (file) {
                console.log("beforeSendFile")
                //  详细的Deferred用法说明，请参照jQuery的API文档。
                //  Deferred对象在钩子回掉函数中经常要用到，用来处理需要等待的异步操作。
                const deferred = WebUploader.Deferred();
                const owner = this.owner;
                // 调用uploader 的MD5 计算方法
                owner.md5File(file.source)
                    // 计算失败
                    .fail(function () {
                        deferred.reject();
                    })
                    // 计算成功
                    .then(function (md5) {
                        // 将MD5 值绑定到文件中
                        file.md5Str = md5;
                    });
            }
        });
    // 初始化Web Uploader
    const uploader = WebUploader.create({
        server: '/file/upload',// 文件接收服务端。
        pick: '#picker',// 选择文件的按钮。可选。内部根据当前运行是创建，可能是input元素，也可能是flash. 这里是div的id
        method: 'POST', // 文件上传方式，POST或者GET，默认Post
        resize: false,// 不压缩image, 默认如果是jpeg，文件上传前会压缩一把再上传！
        chunked: true, //{Boolean} [可选] [默认值：false] 是否要分片处理大文件上传。
        chunkSize: 5 * 1024 * 1024,// {Boolean} [可选] [默认值：5242880] 如果要分片，分多大一片？ 默认大小为5M. 这里设置为
        chunkRetry: 3,// {Boolean} [可选] [默认值：2] 如果某个分片由于网络问题出错，允许自动重传多少次？
        threads: 10, //{Boolean} [可选] [默认值：3] 上传并发数。允许同时最大上传进程数。
        fileNumLimit: 1, //  {int} [可选] [默认值：undefined] 验证文件总数量, 超出则不允许加入队列。
        fileSizeLimit: 2 * 1024 * 1024 * 1024,//最大2GB,{int} [可选] [默认值：undefined] 验证文件总大小是否超出限制, 超出则不允许加入队列。
        fileSingleSizeLimit: 2 * 1024 * 1024 * 1024,//  {int} [可选] [默认值：undefined] 验证单个文件大小是否超出限制, 超出则不允许加入队列。
    });
    /*// 当有文件被添加进队列的时候,展示添加的文件信息
    uploader.on('fileQueued', function (file) {
        $('#list').append('<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<p class="state">等待上传...</p>' +
            '</div>');
    });*/

    // 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。
    uploader.on('uploadBeforeSend', function (obj, data, headers) {

        // data.DelFilePath = parentObj.siblings(".upload-path").val();
        // 这个框架存在这个问题，这里修改访问路径以后，实际是下一次的，因为先初始化地址，再调用此方法
        //  data.ItemCode = $("#txtItemCode").val();
        // 将当前分片序列 传给Minio  参数
        console.log("进入分片，当前分片为：" + data.chunk);
        data.partNumber = data.chunk;
        var aa = data.partNumber;
        const key = "chunk_" + (data.chunk + 1);
        console.log("data[key]:" + data[key])
        uploader.options.server = data[key];// 动态修改文件上传地址
        // 将MD5 传给后台
        console.log("uploadBeforeSend");
        console.log(data)

    });

    uploader.on('fileQueued', function (file) {
        // 选中文件时要做的事情，比如在页面中显示选中的文件并添加到文件列表，获取文件的大小，文件类型等
        console.log(file.ext); // 获取文件的后缀
        console.log(file.size);// 获取文件的大小
        console.log(file.name);
        $('#list').append('<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<p class="state">等待上传...</p>' +
            '</div>');
        uploader.md5File(file)//大文件秒传

            // 及时显示进度
            .progress(function (percentage) {
                console.log('Percentage:', percentage);
            })

            // 完成
            .then(function (val) {
                console.log('md5 result:', val);
            })
    });

    //上传文件点击事件
    function uploadFiles() {
        const filesLength = uploader.getFiles().length;
        const files = uploader.getFiles();
        console.log(files);
        if (filesLength > 0) {
            for (let i = 0; i < filesLength; i++) {
                console.log(files[i].type);
            }
            for (let file in files) {
                // MD5 值绑定到上传请求参数中
                uploader.options.formData.md5 = file.md5;
                console.log('================md5 result:', file);
                console.log(file);
                console.log(uploader.options.formData);
                uploader.upload();
            }
        } else {
            alert("请选择文件！");
        }
    };

    //上传文件
    function uploadFile() {
        const filesLength = uploader.getFiles().length;
        if (filesLength > 0) {
            // 1. 获取上传文件信息
            let files = uploader.getFiles();
            console.log(files);
            //设置为同步
            $.ajaxSettings.async = false;
            let presignedPostFormData = {}
            // 2. 循环待上传文件信息
            for (let index = 0; index < files.length; index++) {
                // 3. 分片上传请求
                let data = {"fileName": files[index].name, "bucketName": "pearl-buckent", "chunkSize": 6};  // 请求参数：文件名称，存储桶名
                console.log(files[index].name);
                let upID;
                $.ajax({
                    type: "GET",
                    url: "/file/createMultipartUpload",
                    data: data,
                    dataType: "json",
                    success: function (res) {
                        presignedPostFormData = res; // 签名数据
                        console.log("获取URL：" + res.url);
                        console.log("获取uploadId：" + res.uploadId)
                        upID = res.uploadId;
                        let list = res.partList; //
                        console.log("上传分片的集合：" + res)

                    },
                });
                // 5. 分片直接上传到MINIO
                files[index].uploadId = upID;

                console.log("开启上传");
                let putUrl = "http://127.0.0.1:9000/pearl-buckent/"
                // 4. 调用签名信息，直接上传到Minio
                presignedPostFormData.key = files[index].name; // 设置key参数的值为文件名
                const PostFormMap = new Map(Object.entries(presignedPostFormData)); // 专为Map
                PostFormMap.set("Content-Type", "*/*"); // 设置Content-Type参数 partNumber
                PostFormMap.set("partNumber", 1);// 需要获取当前上传的分片是哪个
                uploader.options.formData = Object.fromEntries(PostFormMap.entries()); // 将请求参数绑定到uploader
                uploader.options.method = "PUT";
                console.log("开启上传");
                uploader.options.server = presignedPostFormData["chunk_0"];

                console.log(presignedPostFormData["0"]);
                uploader.upload(); // 执行直传到Minio服务器


            }
        } else {
            alert("请选择文件！");
        }
    }

    // 成功uploadSuccess事件
    uploader.on('uploadSuccess', function (file, response) {
        $('#' + file.id).find('p.state').text('上传成功');
        // 6. 合并文件
        console.log("成功uploadSuccess事件");
        console.log(file.uploadId);
        let data22 = {"objectName": file.name, "uploadId": file.uploadId};  // 请求参数：文件名称，存储桶名
        $.ajax({
            async: false,
            type: "GET",
            url: "/file/completeMultipartUpload",
            data: data22,
            dataType: "json",
            success: function (res) {
                console.log("成功合并")

            },
        });


    });
    // 上传失败uploadError事件
    uploader.on('uploadError', function (file) {
        $('#' + file.id).find('p.state').text('上传出错');
    });
    // 不管成功或者失败，在文件上传完后都会触发uploadComplete事件
    uploader.on('uploadComplete', function (file) {
        $('#' + file.id).find('.progress').fadeOut();
    });

</script>
</html>
